package com.code.gen;

import java.io.OutputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.code.gen.bean.bo.CodeGenProperties;
import com.code.gen.bean.bo.CodeGenPropertiesSystem;
import com.code.gen.bean.bo.file.CodeGenFileProperties;
import com.code.gen.bean.bo.template.CodeGenTemplate;
import com.code.gen.enums.ECodeGenDatabaseReadType;
import com.code.gen.enums.ECodeGenTemplateType;
import com.code.gen.enums.ECodeGenType;
import com.code.gen.util.CodeGenDatabaseUtils;
import com.code.gen.util.CodeGenFileUtil;
import com.code.gen.util.CodeGenInitStaticFieldUtil;
import com.code.gen.util.CodeGenPropertiesUtil;
import com.code.gen.util.CodeGenReadTemplate;
import com.sojson.util.gzip.zip.ZipUtil;
import com.sojson.util.servlet.ServletUtil;

/**
 * 代码生成器执行方法
 * 
 * @author liu
 * @date 2022-08-03
 */
public class CodeGenRun {

    /**
     * 运行方法
     * 
     * @param properties
     * @return
     * @throws Exception
     */
    public static Map<String, String> run(CodeGenProperties properties) throws Exception {
        return run(properties, false);
    }

    /**
     * 运行方法
     * 
     * @param properties
     * @param show          是否预览
     * @return
     * @throws Exception
     */
    public static Map<String, String> run(CodeGenProperties properties, boolean show) throws Exception {
        Map<String, String> templates = new LinkedHashMap<>();
        // 初始化程序数据
        new CodeGenInitStaticFieldUtil(properties).init();

        // 从数据库读取数据
        new CodeGenDatabaseUtils(properties).readDatabase();

        // 初始化属性
        CodeGenPropertiesUtil propertiesUtil = new CodeGenPropertiesUtil(properties);
        propertiesUtil.initProperties();

        // 读取模板文件并给模板配置对应的占位符
        CodeGenReadTemplate codeGenReadTemplate = new CodeGenReadTemplate(properties);
        codeGenReadTemplate.readTemplate();

        List<CodeGenFileProperties> files = properties.getFiles();
        Map<String, byte[]> hashMap = new HashMap<>(20);
        for (CodeGenFileProperties file : files) {
            // 初始化集合
            // 要生成的模板
            properties.setContents(new LinkedHashMap<>(20));
            // 模板占位符
            properties.setPlaceholders(new HashMap<>(100));

            // 初始化属性
            propertiesUtil.initProperties(file);

            // 合并模板
            codeGenReadTemplate.merged(file);

            // 初始化文件生成路径
            codeGenReadTemplate.initGeneratePath(file);

            // 创建文件
            if (show) {
                Map<String, CodeGenTemplate> contents = properties.getContents();
                Set<Entry<String, CodeGenTemplate>> entrySet = contents.entrySet();
                for (Entry<String, CodeGenTemplate> entry : entrySet) {
                    if (ECodeGenTemplateType.MAIN == entry.getValue().getType()) {
                        CodeGenTemplate value = entry.getValue();
                        templates.put(value.getId() + value.getFileNameSuffix(), value.getContent());
                    }
                }
            } else {
                CodeGenFileUtil codeGenFileUtil = new CodeGenFileUtil(properties);
                if (file.getGenType() == ECodeGenType.THIS.getCode()
                    || file.getGenType() == ECodeGenType.PATH.getCode()) {
                    codeGenFileUtil.createFile();
                } else if (file.getGenType() == ECodeGenType.DOWNLOAD.getCode()) {
                    codeGenFileUtil.getZip(hashMap);
                }
            }
        }

        if (hashMap.size() > 0) {
            byte[] bytes = ZipUtil.getBytes(hashMap);
            OutputStream out = ServletUtil.getResponseFile("code.zip").getOutputStream();
            out.write(bytes);
        }
        return templates;
    }

    /**
     * 离线模式运行
     * 
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        CodeGenProperties properties = new CodeGenProperties();
        initProperties(properties.getSystem());
        run(properties);
    }

    /**
     * 初始化系统配置
     * 
     * @param system
     * @throws Exception 
     */
    private static void initProperties(CodeGenPropertiesSystem system) throws Exception {
        String databaseName = system.getDatabaseName();
        if (databaseName == null) {
            system.setReadType(ECodeGenDatabaseReadType.OFFLINE);
        } else {
            system.setReadType(ECodeGenDatabaseReadType.OTHER);
        }
    }

}